/*
 * PacketFileSource.cpp
 *
 *  Created on: 2016年10月9日
 *      Author: zhengboyuan
 */

#include "PacketFileSource.h"
#include "MediaFormatJson.h"
#include <json/writer.h>
#include "TByteBuffer.h"



namespace av
{

const char*	PacketFileSource::FILE_EXT = ".pkt";

PacketFileSource::PacketFileSource():
		m_curTime()
{
}

PacketFileSource::~PacketFileSource()
{
	close();
}

int PacketFileSource::open(const std::string& url, const std::string& params)
{
	std::string idxPath = url + ".idx";

	if (!m_indexFile.open(idxPath.c_str()))
	{
		return ENOENT;
	}

	m_ifs.open(url.c_str(), std::ios::binary|std::ios::in);
	if (!m_ifs.is_open())
	{
		return ENOENT;
	}

	if (!readFormat())
	{
		return EBADF;
	}

	m_format.m_duration = m_indexFile.getDuration() / 1000;

	return 0;
}

void PacketFileSource::close()
{
	m_ifs.close();
	m_indexFile.close();
}

bool PacketFileSource::isOpen()
{
	return m_ifs.is_open();
}

bool PacketFileSource::getFormat(MediaFormat& fmt)
{
	fmt = m_format;
	return true;
}

int PacketFileSource::getDuration()
{
	return m_format.m_duration;
}

int PacketFileSource::play()
{
	return 0;
}

int PacketFileSource::pause()
{
	return 0;
}

void PacketFileSource::stop()
{
	//
}

int PacketFileSource::getState()
{
	return STATE_PLAYING;
}

bool PacketFileSource::seekable()
{
	return true;
}

int PacketFileSource::seek(int64_t offset)
{
	PacketIndex index;
	if (!m_indexFile.locate(offset, index))
	{
		return ERANGE;
	}

	m_ifs.seekg(index.offset);

	return 0;
}

int64_t PacketFileSource::getTime()
{
	return m_curTime;
}

int PacketFileSource::setScale(float scale)
{
	return 0;
}

float PacketFileSource::getScale()
{
	return 1.0;
}

int PacketFileSource::read(AVPacket& pkt)
{
	PacketHeader hdr;
	memset(&hdr, 0, sizeof(hdr));
	m_ifs.read((char*)&hdr, sizeof(hdr));
	if (!m_ifs.good())
	{
		return AVERROR_EOF;
	}

	if (pkt.data == NULL)
	{
		av_new_packet(&pkt, hdr.size);
	}
	else
	{
		av_grow_packet(&pkt, hdr.size);
	}
	
	m_ifs.read((char*)pkt.data, hdr.size);
	if (!m_ifs.good())
	{
		return AVERROR_EOF;
	}

	if (hdr.tag != kPacket)
	{
		return AVERROR(EAGAIN);
	}

	pkt.stream_index = hdr.type;
	pkt.duration = hdr.duration;
	pkt.flags = hdr.flags;
	pkt.dts = hdr.ts;
	pkt.pts = hdr.ts;

	m_curTime = hdr.ts;

	if (pkt.flags != 0)
	{
		if (m_indexFile.reload())
		{
			m_format.m_duration = m_indexFile.getDuration() / 1000;
		}
	}

	return 0;
}

void PacketFileSource::interrupt()
{
	// pass
}

bool PacketFileSource::isLive()
{
	return false;
}

bool PacketFileSource::getMetaData(const std::string& key, std::string& value)
{
	return false;
}

bool PacketFileSource::readFormat()
{
	PacketHeader hdr;
	memset(&hdr, 0, sizeof(hdr));
	m_ifs.read((char*)&hdr, sizeof(hdr));
	if (!m_ifs.good())
	{
		return false;
	}

	if (hdr.tag != av::kFormat)
	{
		return false;
	}

	comn::ByteBuffer buffer;
	buffer.ensure(hdr.size);
	m_ifs.read((char*)buffer.data(), hdr.size);
	if (!m_ifs.good())
	{
		return false;
	}

	Json::Value value;
	Json::Reader reader;
	if (!reader.parse(buffer.c_str(), buffer.c_str() + hdr.size, value))
	{
		return false;
	}

	return MediaFormatJson::fromJson(m_format, value);
}



} /* namespace av */
